package com.xuecheng.order.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.UUID;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xuecheng.commons.constants.OrdersConstants;
import com.xuecheng.commons.enums.ErrorCode;
import com.xuecheng.commons.model.dto.MyOrderDto;
import com.xuecheng.commons.model.dto.PageRequest;
import com.xuecheng.commons.model.dto.RecordDto;
import com.xuecheng.commons.model.vo.*;
import com.xuecheng.commons.utils.AuthInfoHolder;
import com.xuecheng.commons.utils.BeanHelper;
import com.xuecheng.learning.api.LearningClient;
import com.xuecheng.order.domain.Orders;
import com.xuecheng.order.domain.Payment;
import com.xuecheng.order.mappers.OrdersMapper;
import com.xuecheng.order.service.OrdersService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xuecheng.order.service.PaymentService;
import com.xuecheng.order.utils.PayUtils;
import com.xuecheng.search.api.SearchClient;
import com.xuecheng.web.exception.BusinessException;
import io.seata.spring.annotation.GlobalTransactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * 订单 服务实现类
 * </p>
 *
 * @author itheima
 * @since 2022-07-26
 */
@Service
public class OrdersServiceImpl extends ServiceImpl<OrdersMapper, Orders> implements OrdersService {
        // 先根据课程id搜索课程 远程调用feign
        @Autowired
        private SearchClient searchClient;
        @Autowired
        private PayUtils payUtils;
        @Autowired
        private PaymentService paymentService;
        @Autowired
        private LearningClient learningClient;

        /**
         * 课程下单：创建订单数据存入数据库，返回订单号
         *
         * @param coursePubId 课程id
         * @return 订单号
         */
        @Override
        public ResponseResult<String> createOrder(Long coursePubId) {
                //1、获取当前用户id
                Long userId = AuthInfoHolder.getUserId();
                //2、查询当前用户是否已经购买过此课程:
                LambdaQueryWrapper<Orders> qw1 = new LambdaQueryWrapper();
                qw1.eq(Orders::getUserId, userId);
                qw1.eq(Orders::getCoursePubId, coursePubId);
                qw1.eq(Orders::getStatus, OrdersConstants.ORDER_PAID_STATUS);
                Orders one1 = this.getOne(qw1);
                if (one1 != null) {
                        throw new BusinessException(ErrorCode.ORDERERROR);
                }
                //3、查询当前课程是否已经具备初始态的订单，如果存在，返回订单号
                LambdaQueryWrapper<Orders> qw2 = new LambdaQueryWrapper();
                qw2.eq(Orders::getUserId, userId);
                qw2.eq(Orders::getCoursePubId, coursePubId);
                qw2.eq(Orders::getStatus, OrdersConstants.ORDER_INIT_STATUS);
                Orders one2 = this.getOne(qw2);
                if (one2 != null) {
                        return ResponseResult.okResult(one2.getOrderNo());
                }
                //4、构造订单数据
                ResponseResult<CoursePubIndexVo> result = searchClient.findById(coursePubId);
                CoursePubIndexVo coursePub = result.getData(); //课程发布数据
                if (coursePub == null) {
                        throw new BusinessException(ErrorCode.PAYERROR);
                }
                Orders orders = new Orders();
                orders.setOrderNo(UUID.randomUUID().toString(true)); //唯一的字符串
                orders.setCoursePubId(coursePubId);
                orders.setCoursePubName(coursePub.getName());
                orders.setCompanyId(coursePub.getCompanyId());
                orders.setUserId(userId);
                orders.setCreateDate(new Date());
                orders.setPrice(1L); //单位是分，1分钱
                orders.setStatus(OrdersConstants.ORDER_INIT_STATUS);
                //5、存入到数据库中
                boolean save = this.save(orders);
                if (!save) {
                        throw new BusinessException(ErrorCode.PAYERROR);
                }
                //6、构造返回值
                return ResponseResult.okResult(orders.getOrderNo());
        }

        @Override
        @GlobalTransactional
        public ResponseResult queryOrders(String orderNo) {
                // 根据订单号判断订单是否存在
                LambdaQueryWrapper<Orders> qw = new LambdaQueryWrapper<>();
                qw.eq(Orders::getOrderNo, orderNo);
                Orders order = this.getOne(qw);
                if (order == null) {
                        throw new BusinessException(ErrorCode.NOTFOUND);
                }
                // 如果订单状态 = 未支付，查询微信的支付结果
                if (order.getStatus().equals(OrdersConstants.ORDER_INIT_STATUS)) {
                        Boolean payment = payUtils.checkPayment(orderNo);
                        if (payment) {
                                // 如果存在微信订单结果
                                // 1 修改订单表
                                order.setStatus(OrdersConstants.ORDER_PAID_STATUS);
                                this.updateById(order);
                                // 2 修改支付信息表
                                LambdaQueryWrapper<Payment> pqw = new LambdaQueryWrapper<>();
                                pqw.eq(Payment::getOrderNo, orderNo);
                                Payment payment1 = new Payment();
                                payment1.setStatus(OrdersConstants.PAID.toString());
                                paymentService.update(payment1, pqw);
                                // 3 远程调用 更新选课记录
                                RecordDto recordDto = new RecordDto();
                                recordDto.setCoursePubId(order.getCoursePubId());
                                recordDto.setUserId(order.getUserId());
                                learningClient.saveRecord(recordDto);
                        }
                }
                // 构建返回值
                OrdersVo vo = BeanHelper.copyProperties(order, OrdersVo.class);
                return ResponseResult.okResult(vo);
        }

        @Override
        public void getPayment() {
                // 查询 状态为 超时/未支付 的订单
                LambdaQueryWrapper<Orders> qw = new LambdaQueryWrapper<>();
                qw.eq(Orders::getStatus, OrdersConstants.ORDER_INIT_STATUS);
                String time = DateUtil.offsetMinute(new Date(), -15).toString();
                qw.lt(Orders::getCreateDate, time);
                List<Orders> ordersList = this.list(qw);
                // 循环所有超时订单
                if (ordersList != null) {
                        for (Orders order : ordersList) {
                                // 获取订单 调用微信服务查询订单支付状态
                                Boolean payment = payUtils.checkPayment(order.getOrderNo());
                                if (payment) {
                                        // 如果存在微信订单结果
                                        // 1 修改订单表
                                        order.setStatus(OrdersConstants.ORDER_PAID_STATUS);
                                        this.updateById(order);
                                        // 2 修改支付信息表
                                        LambdaQueryWrapper<Payment> pqw = new LambdaQueryWrapper<>();
                                        pqw.eq(Payment::getOrderNo, order.getOrderNo());
                                        Payment payment1 = new Payment();
                                        payment1.setStatus(OrdersConstants.PAID.toString());
                                        paymentService.update(payment1, pqw);
                                        // 3 远程调用 更新选课记录
                                        RecordDto recordDto = new RecordDto();
                                        recordDto.setCoursePubId(order.getCoursePubId());
                                        recordDto.setUserId(order.getUserId());
                                        learningClient.saveRecord(recordDto);
                                } else {
                                        // 如果未支付 调用微信支付工具 关闭订单
                                        Boolean closeOrder = payUtils.closeOrder(order.getOrderNo());
                                        if (closeOrder) {
                                                order.setStatus(OrdersConstants.ORDER_CLOSED_STATUS);
                                                this.updateById(order);
                                        }
                                }
                        }
                }
        }

        @Override
        public ResponseResult myOrdersList(PageRequest pageRequest, MyOrderDto dto) {
                LambdaQueryWrapper<Orders> qw = new LambdaQueryWrapper<>();
                Page<Orders> page = new Page<>(pageRequest.getPageNo(), pageRequest.getPageSize());
//                if(AuthInfoHolder.getUserId() == null){
//                        throw new BusinessException(ErrorCode.ERROR);
//                }else {
//                        qw.eq(Orders::getUserId,AuthInfoHolder.getUserId());
//                }
                if (dto.getOrderNo() != null) {
                        qw.eq(Orders::getOrderNo, dto.getOrderNo());
                }
                if (dto.getStatus() != null) {
                        qw.eq(Orders::getStatus, dto.getStatus());
                }
                IPage<Orders> ordersPage = this.page(page, qw);
                List<Orders> orders = ordersPage.getRecords();
                List<MyOrderVo> vos = BeanHelper.copyWithCollection(orders, MyOrderVo.class);
                return PageResponseResult.okResult(ordersPage.getTotal(),vos);
        }

        @Override
        public ResponseResult ordersExcel(Long companyId) throws FileNotFoundException {
                if(companyId == null){
                        throw new BusinessException(ErrorCode.PARAMSERROR);
                }
                LambdaQueryWrapper<Orders> qw = new LambdaQueryWrapper<>();
                qw.eq(Orders::getCompanyId,companyId);
                List<Orders> ordersList = this.list(qw);
                EasyExcel.write(new FileOutputStream("e:/orderExcel.xlsx"),OrdersExcelVo.class)
                        .sheet("sheet1").doWrite(ordersList);
                return ResponseResult.okResult();
        }

        @Override
        public ResponseResult countOrders(PageRequest pageRequest, MyOrderDto dto) {
                Page<Orders> page = new Page<>(pageRequest.getPageNo(), pageRequest.getPageSize());
                LambdaQueryWrapper<Orders> qw = new LambdaQueryWrapper<>();
                if (dto.getOrderNo() != null) {
                        qw.eq(Orders::getOrderNo, dto.getOrderNo());
                }
                if (dto.getStatus() != null) {
                        qw.eq(Orders::getStatus, dto.getStatus());
                }
                if (!StringUtils.isEmpty(dto.getCourseName())) {
                        qw.like(Orders::getCoursePubName,dto.getCourseName());
                }
                if(!StringUtils.isEmpty(dto.getOrderStart()) && !StringUtils.isEmpty(dto.getOrderEnd())){
                        qw.gt(Orders::getCreateDate,dto.getOrderStart());
                        qw.lt(Orders::getCreateDate,dto.getOrderEnd());
                }
                IPage<Orders> ordersPage = this.page(page, qw);
                List<Orders> orders = ordersPage.getRecords();
                List<MyOrderVo> vos = BeanHelper.copyWithCollection(orders, MyOrderVo.class);
                return PageResponseResult.okResult(ordersPage.getTotal(),vos);
        }
}
